import type { MapDataItem } from "./extractModelData";
import { loadGLTFModel, destroyGLTFModel } from "./loadGLTFModel";
import { InfoWindowService } from "./infoWindowService";

/**
 * 模型服务类，负责模型的加载、创建、销毁和管理
 */
export class ModelService {
  private TMap: any = null;
  private map: any = null;
  private modelInstances: Map<string, any> = new Map();
  private infoWindowService: InfoWindowService | null = null;

  /**
   * 构造函数
   * @param TMap TMap API实例
   * @param map 地图实例
   */
  constructor(TMap: any, map: any) {
    this.TMap = TMap;
    this.map = map;
    this.infoWindowService = new InfoWindowService(TMap, map);
  }

  /**
   * 判断点是否在地图视口范围内（带缓冲区）
   * @param lat 纬度
   * @param lon 经度
   * @returns boolean 是否在视口内
   */
  public isPointInViewport(lat: number, lon: number): boolean {
    if (!this.map || !this.TMap) return false;

    try {
      // 获取地图当前视口的边界
      const bounds = this.map.getBounds();
      // 创建点坐标
      const point = new this.TMap.LatLng(lat, lon);

      // 获取边界的经纬度范围
      const ne = bounds.getNorthEast();
      const sw = bounds.getSouthWest();

      // 创建带缓冲区的新边界
      const bufferedNe = new this.TMap.LatLng(ne.getLat(), ne.getLng());
      const bufferedSw = new this.TMap.LatLng(sw.getLat(), sw.getLng());
      const bufferedBounds = new this.TMap.LatLngBounds(bufferedSw, bufferedNe);

      // 判断点是否在带缓冲区的边界内
      return bufferedBounds.contains(point);
    } catch (error) {
      console.error("判断点是否在视口内失败:", error);
      return false;
    }
  }

  /**
   * 解析polygon字符串中的coordinates为TMap.LatLng数组
   * @param polygonStr polygon字符串
   * @returns TMap.LatLng[] 坐标数组
   */
  public parsePolygonToMaskPath(polygonStr: string): any[] {
    try {
      const polygon = JSON.parse(polygonStr);
      const coordinates = polygon?.coordinates?.[0] || [];

      // 转换经纬度坐标为TMap.LatLng对象
      const maskPath: any[] = coordinates.map((coord: number[]) => {
        // 注意：coordinates格式为[lon, lat]
        return new this.TMap.LatLng(coord[1], coord[0]);
      });

      return maskPath;
    } catch (error) {
      console.error("解析polygon失败:", error);
      return [];
    }
  }

  /**
   * 创建单个模型实例
   * @param modelData 模型数据对象
   */
  public createSingleModel(modelData: MapDataItem): void {
    if (!this.TMap || !this.map || !modelData) return;

    try {
      // 确保有必要的字段
      if (
        !modelData.lat ||
        !modelData.lon ||
        !modelData.id ||
        !modelData.httpUrl ||
        !modelData.polygon
      ) {
        console.warn(
          "模型数据不完整，跳过创建:",
          modelData.name || modelData.id
        );
        return;
      }

      // 解析polygon中的coordinates作为mask路径
      const maskPath = this.parsePolygonToMaskPath(modelData.polygon);

      if (maskPath.length === 0) {
        console.warn(
          "无法解析有效的mask路径，跳过创建模型:",
          modelData.name || modelData.id
        );
        return;
      }

      // 创建模型实例
      const instance = loadGLTFModel(this.TMap, {
        url: modelData.httpUrl,
        map: this.map,
        id: `model_${modelData.id}`, // 使用数据中的id
        position: new this.TMap.LatLng(modelData.lat, modelData.lon), // 使用数据中的经纬度
        scale: [7.5, 7.5, 7.5], // 模型缩放比例
        mask: maskPath, // 使用解析的mask路径
        onLoaded: () => {
          console.log(`模型加载成功: ${modelData.name || modelData.id}`);
        },
        onLoadFailed: () => {
          console.error(
            `模型加载失败: ${modelData.name || modelData.id}`,
            modelData.httpUrl
          );
        },
      });

      // 存储模型实例引用
      this.modelInstances.set(`${modelData.id}`, instance);

      // 创建信息窗口
      if (this.infoWindowService) {
        this.infoWindowService.createInfoWindow(modelData);
      }
    } catch (error) {
      console.error(`创建模型时出错: ${modelData.name || modelData.id}`, error);
    }
  }

  /**
   * 加载当前视口内的模型
   * @param modelDataList 模型数据列表
   */
  public loadModelsInViewport(modelDataList: MapDataItem[]): void {
    if (!this.TMap || !this.map || !modelDataList || modelDataList.length === 0)
      return;

    console.log("开始加载视口内模型，总数据数量:", modelDataList.length);

    // 获取当前已加载的模型ID集合
    const loadedModelIds = new Set<string>(this.modelInstances.keys());
    // 存储本次需要保留的模型ID
    const keepModelIds = new Set<string>();

    // 遍历所有模型数据
    modelDataList.forEach((item: MapDataItem) => {
      const modelId = `${item.id}`;

      // 检查模型是否在视口内
      if (this.isPointInViewport(item.lat, item.lon)) {
        keepModelIds.add(modelId);

        // 如果模型不在已加载列表中，则创建
        if (!loadedModelIds.has(modelId)) {
          this.createSingleModel(item);
        }
      }
    });

    // 销毁不在视口内的模型和信息窗口
    loadedModelIds.forEach((modelId) => {
      if (!keepModelIds.has(modelId)) {
        this.destroySingleModel(modelId);
      }
    });

    console.log(`当前视口内加载的模型数量: ${this.modelInstances.size}`);
  }

  /**
   * 销毁单个模型
   * @param modelId 模型ID
   */
  public destroySingleModel(modelId: string): void {
    const instance = this.modelInstances.get(modelId);
    if (instance) {
      destroyGLTFModel(instance);
      this.modelInstances.delete(modelId);
      console.log(`销毁模型: ${modelId}`);
    }

    // 销毁对应的信息窗口
    if (this.infoWindowService) {
      this.infoWindowService.destroyInfoWindow(modelId);
    }
  }

  /**
   * 清理所有模型实例
   */
  public clearAllModels(): void {
    this.modelInstances.forEach((instance, id) => {
      if (instance) {
        destroyGLTFModel(instance);
      }

      // 销毁对应的信息窗口
      if (this.infoWindowService) {
        this.infoWindowService.destroyInfoWindow(id);
      }
    });
    this.modelInstances.clear();
  }

  /**
   * 获取当前加载的模型数量
   * @returns 模型数量
   */
  public getModelCount(): number {
    return this.modelInstances.size;
  }

  /**
   * 获取信息窗口服务实例
   * @returns 信息窗口服务实例
   */
  public getInfoWindowService(): InfoWindowService | null {
    return this.infoWindowService;
  }

  /**
   * 更新地图实例引用
   * @param map 新的地图实例
   */
  public updateMapInstance(map: any): void {
    this.map = map;
    if (this.infoWindowService) {
      this.infoWindowService.updateMapInstance(map);
    }
    // 重新创建所有模型
    this.clearAllModels();
  }

  /**
   * 销毁服务
   */
  public destroy(): void {
    this.clearAllModels();
    if (this.infoWindowService) {
      this.infoWindowService.destroyAllInfoWindows();
      this.infoWindowService = null;
    }
  }
}
